package com.cr.framework.config;

import com.cr.common.constant.CacheConstants;
import com.cr.common.core.redis.RedisCache;
import com.cr.common.utils.SecurityUtils;
import com.cr.common.utils.StringUtils;
import com.cr.framework.web.service.AppUserDetailsServiceImpl;
import lombok.SneakyThrows;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;

@Component("appAuthenticationProvider")
public class AppAuthenticationProvider implements AuthenticationProvider {

    @Resource(name = "appUserDetailsService")
    private AppUserDetailsServiceImpl userDetailsService;

    @Resource
    private RedisCache redisCache;

    @SneakyThrows
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = authentication.getName();
        Object password = authentication.getCredentials();

        // 这里构建来判断用户是否存在和密码是否正确
        UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
        if(! SecurityUtils.matchesPassword(password.toString(), userDetails.getPassword())){

            // 临时密码校验
            String verifyKey = CacheConstants.APP_USER_TEMP_PWD_KEY + userDetails.getUsername();
            String tempPwd = redisCache.getCacheObject(verifyKey);
            if(StringUtils.isBlank(tempPwd) ||
                    ! SecurityUtils.matchesPassword(password.toString(), tempPwd)) {
                throw new Exception("用户不存在或密码错误！");
            }
        }
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
        // 构建返回的用户登录成功的token
        return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}
